/*
 * EmuladorP.java
 *
 * Created on 16 de enero de 2008, 18:14
 */
package maquinaVirtual;

import java.awt.Color;
import java.awt.Toolkit;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;


/**
 *
 * @author Miguel Angel Diaz
 * @author David Martin
 * @version 1.0
 */
public class EmuladorP extends javax.swing.JFrame {
    
	private static final long serialVersionUID = 1L;
	
	MaquinaP mp;
    
    public EmuladorP() {        
        creaVentana();
        actualiza();        
    }
    
    public EmuladorP(String ruta) {        
    	creaVentana();
    	mp.cargarPrograma(ruta);
    	if (mp.programaCargado())
    		setTitle("Emulador Maquina P - " + new File(ruta).getName());
    	actualiza();	
    }
    
    private void creaVentana(){    	
    	mp = new MaquinaP();        
        inicializaComponentes();        
        
        // Centrar ventana en pantalla
        try {
            Dimension ventana = Toolkit.getDefaultToolkit().getScreenSize();
            int alto = ventana.height;
            int ancho = ventana.width;
            this.setLocation(ancho/2-this.getWidth()/2, alto/2-this.getHeight()/2);
        } catch (Exception e) {
            this.setLocation(0,0);
        }
        
        setResizable(false);
    }
    
    public void actualiza(){
    	
        // Actualiza la pila
        ArrayList<String> pila = new ArrayList<String>();
        for (int i=0; i<(10-mp.getPila().size()); i++)
            pila.add(" ");
        for (int i=mp.getPila().size()-1; i>=0; i--)
            pila.add(i + "@  " + mp.getPila().get(i).toString());
        jList1.setListData(pila.toArray());
            
        // Actualiza la memoria de instrucciones
        ArrayList<String> mInstr = new ArrayList<String>();
        for (int i=0; i<mp.getMInstr().size(); i++)
        	mInstr.add(i + "@  " + mp.getPosMInstr(i));
        jList2.setListData(mInstr.toArray());
        jList2.setSelectedIndex(mp.getCP());
        jList2.ensureIndexIsVisible(mp.getCP());
        
        // Actualiza la memoria de datos
        ArrayList<String> mDatos = new ArrayList<String>();
        for (int i=0; i<mp.getMDatos().size(); i++)
        	if (mp.getPosMDatos(i) != Integer.MIN_VALUE)
        		mDatos.add(i + "@  " + mp.getPosMDatos(i));
        	else
        		mDatos.add(i + "@");
        jList3.setListData(mDatos.toArray());
        
        // Actualiza el contador de programa
        jTextField1.setText(Integer.toString(mp.getCP()));
        jTextField1.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        
        // Actualiza el estado
        jTextField2.setText(mp.getF()+"");
        jTextField2.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        
        // Actualiza el mensaje de informacion
        jTextField3.setText(mp.getInfo());
    	if (mp.getF() == 'e')
        	jTextField3.setForeground(Color.red);
        else if (mp.getF() == 's')
            jTextField3.setForeground(Color.blue);
    }
    
    /** Inicializa todos los componentes de la ventana
     */
    private void inicializaComponentes() {
        jDesktopPane1 = new javax.swing.JDesktopPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList2 = new javax.swing.JList();
        jScrollPane3 = new javax.swing.JScrollPane();
        jList3 = new javax.swing.JList();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        botonReiniciar = new javax.swing.JButton();
        botonPasos = new javax.swing.JButton();
        botonTodo = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jTextField2 = new javax.swing.JTextField();
        jTextField3 = new javax.swing.JTextField();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem3 = new javax.swing.JMenuItem();
        
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Emulador Maquina P");
        jDesktopPane1.setBackground(new java.awt.Color(204, 255, 153));
        jList1.setModel(new javax.swing.AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = { };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jList1.setToolTipText("Contenido de la pila");
        jScrollPane1.setViewportView(jList1);

        jScrollPane1.setBounds(20, 40, 75, 190);
        jDesktopPane1.add(jScrollPane1, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jList2.setModel(new javax.swing.AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = { };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList2.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jList2.setToolTipText("Contenido de la Memoria de Instrucciones");
        jScrollPane2.setViewportView(jList2);

        jScrollPane2.setBounds(100, 40, 155, 190);
        jDesktopPane1.add(jScrollPane2, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jList3.setModel(new javax.swing.AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = { };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList3.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jList3.setToolTipText("Contenido de la Memoria de Datos");
        jScrollPane3.setViewportView(jList3);

        jScrollPane3.setBounds(260, 40, 80, 190);
        jDesktopPane1.add(jScrollPane3, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jLabel1.setText("Pila");
        jLabel1.setBounds(20, 20, 40, 20);
        jDesktopPane1.add(jLabel1, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jLabel2.setText("Memoria Instrucciones");
        jLabel2.setBounds(100, 20, 160, 20);
        jDesktopPane1.add(jLabel2, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jLabel3.setText("Memoria Datos");
        jLabel3.setBounds(260, 20, 120, 20);
        jDesktopPane1.add(jLabel3, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonReiniciar.setText("Reiniciar");
        botonReiniciar.setToolTipText("Vuelve la Maquina P al estado inicial");
        botonReiniciar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonReiniciaActionPerformed(evt);
            }
        });
        botonReiniciar.setBounds(430, 240, 100, 23);
        jDesktopPane1.add(botonReiniciar, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonPasos.setText("Ejecutar por pasos");
        botonPasos.setToolTipText("Ejecuta el programa instruccion a instruccion");
        botonPasos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonPasosActionPerformed(evt);
            }
        });
        botonPasos.setBounds(210, 240, 200, 23);
        jDesktopPane1.add(botonPasos, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonTodo.setText("Ejecutar todo");
        botonTodo.setToolTipText("Ejecuta todo el programa desde CP");
        botonTodo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonTodoActionPerformed(evt);
            }
        });
        botonTodo.setBounds(20, 240, 170, 23);
        jDesktopPane1.add(botonTodo, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jLabel4.setText("Contador de Programa");
        jLabel4.setBounds(370, 40, 130, 20);
        jDesktopPane1.add(jLabel4, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jTextField1.setEditable(false);
        jTextField1.setBounds(400, 70, 59, 20);
        jTextField1.setToolTipText("Posicion de la siguiente instruccion a ejecutar");
        jDesktopPane1.add(jTextField1, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jLabel5.setText("Estado");
        jLabel5.setBounds(410, 120, 80, 20);
        jDesktopPane1.add(jLabel5, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jTextField2.setEditable(false);
        jTextField2.setBounds(400, 150, 59, 20);
        jTextField2.setToolTipText("Estado de la Maquina P");
        jDesktopPane1.add(jTextField2, javax.swing.JLayeredPane.DEFAULT_LAYER);
        
        jTextField3.setEditable(false);
        jTextField3.setBounds(20, 270, 510, 20);
        jDesktopPane1.add(jTextField3, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jMenu1.setText("Archivo");
        jMenuItem1.setText("Abrir");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuAbrirActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuItem2.setText("Salir");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuSalirActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem2);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Ayuda");
        jMenuItem3.setText("Manual");
        jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuManualActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem3);
  
        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jDesktopPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 550, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jDesktopPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE)
        );
        pack();
    }

    private void menuManualActionPerformed(java.awt.event.ActionEvent evt) {
        try{
            BufferedReader flujo = new BufferedReader(new FileReader("Manual.txt"));
            String frase = flujo.readLine();
            String mensaje = "";
            while(frase != null){
                mensaje += frase+"\n";
                frase = flujo.readLine();
            }
            Ventana aux=new Ventana(mensaje);
            aux.setVisible(true);
        }
        catch(Exception e){
        	JOptionPane.showMessageDialog(this,"Archivo \"Manual.txt\" no encontrado","Error",JOptionPane.ERROR_MESSAGE);
        }
    }

    private void menuSalirActionPerformed(java.awt.event.ActionEvent evt) {
        dispose();
    }

    private void botonReiniciaActionPerformed(java.awt.event.ActionEvent evt) {
        mp.reinicia();
        actualiza();
    }

    private void botonPasosActionPerformed(java.awt.event.ActionEvent evt) {
        if (mp.programaCargado()){
        	mp.ejecutaInstruccion();
        	actualiza();
        }
        else
        	JOptionPane.showMessageDialog(this, "No hay programa cargado", "Info", JOptionPane.INFORMATION_MESSAGE);
    }

    private void botonTodoActionPerformed(java.awt.event.ActionEvent evt) {
    	if (mp.programaCargado()){
        	mp.ejecutaPrograma();
        	actualiza();
        }
        else
        	JOptionPane.showMessageDialog(this, "No hay programa cargado", "Info", JOptionPane.INFORMATION_MESSAGE);
    }

    private void menuAbrirActionPerformed(java.awt.event.ActionEvent evt) {
        JFileChooser jFileChooser= new JFileChooser();
        jFileChooser.setCurrentDirectory(new File("."));
        jFileChooser.setMultiSelectionEnabled(false);
        jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        jFileChooser.setFileFilter(new Filtro());
        jFileChooser.showOpenDialog(this);
        try {
            String fichero=jFileChooser.getSelectedFile().getPath();
            mp.reinicia();
            mp.cargarPrograma(fichero);
            if (mp.programaCargado())
            	setTitle("Emulador Maquina P - " + jFileChooser.getSelectedFile().getName());
            actualiza();            
        }
        catch (Exception e){            
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(final String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
            	if (args.length == 0)
            		new EmuladorP().setVisible(true);
            	else if (args.length == 1)
            		new EmuladorP(args[0]).setVisible(true);
            	else System.out.println("Uso: java -jar EmuladorP.jar [archivo]");
            }
        });
    }
    
    private javax.swing.JButton botonReiniciar;
    private javax.swing.JButton botonPasos;
    private javax.swing.JButton botonTodo;
    private javax.swing.JDesktopPane jDesktopPane1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JList jList1;
    private javax.swing.JList jList2;
    private javax.swing.JList jList3;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    
}
